// Author. Du Haihang

/*
// Use <button> to bind clipboard for Mobile

<button class="copy-link-button">COPY LINK</button>
.copy-link-button{
	position: absolute; top:50px; left:50px;
	outline: none;
	border:none;
	background:none;
}

const clipboard = new Clipboard('.copy-link-button', {
	text: 'your message to copied-!', // "copy" message
	onComplete: (e)=> {
		alert("Copied:" + e.text);
	},
	onError:(e)=> {
		alert("error: " + e.text);
	}
});

*/

function select(element) {
	let selectedText;

	if (element.nodeName === 'SELECT') {
		element.focus();

		selectedText = element.value;
	} else if (element.nodeName === 'INPUT' || element.nodeName === 'TEXTAREA') {
		const isReadOnly = element.hasAttribute('readonly');

		if (!isReadOnly) {
			element.setAttribute('readonly', '');
		}
		element.select();
		element.setSelectionRange(0, element.value.length);
		if (!isReadOnly) {
			element.removeAttribute('readonly');
		}
		selectedText = element.value;
	} else {
		if (element.hasAttribute('contenteditable')) {
			element.focus();
		}

		const selection = window.getSelection();
		const range = document.createRange();

		range.selectNodeContents(element);
		selection.removeAllRanges();
		selection.addRange(range);

		selectedText = selection.toString();
	}

	return selectedText;
}

const DOCUMENT_NODE_TYPE = 9;
if (typeof Element !== 'undefined' && !Element.prototype.matches) {
	const proto = Element.prototype;
	proto.matches =
		proto.matchesSelector ||
		proto.mozMatchesSelector ||
		proto.msMatchesSelector ||
		proto.oMatchesSelector ||
		proto.webkitMatchesSelector;
}

function closest(element, selector) {
	while (element && element.nodeType !== DOCUMENT_NODE_TYPE) {
		if (element.matches(selector)) return element;
		element = element.parentNode;
	}
}

function delegate(element, selector, type, callback, useCapture) {
	const listenerFn = listener.apply(this, arguments);
	element.addEventListener(type, listenerFn, useCapture);
	return {
		destroy() {
			element.removeEventListener(type, listenerFn, useCapture);
		}
	};
}

function listener(element, selector, type, callback) {
	return (e) => {
		e.delegateTarget = closest(e.target, selector);
		if (e.delegateTarget) {
			callback.call(element, e);
		}
	};
}

function listenSelector(selector, type, callback) {
	return delegate(document.body, selector, type, callback);
}

export function ClipboardAction(options) {
	const action = options.action;
	const container = options.container;
	const text = options.text;
	const element = options.element;
	const onComplete = options.onComplete != undefined ? options.onComplete : null;
	const onError = options.onError != undefined ? options.onError : null;
	let selectedText = '';
	let fakeHandlerCallback;
	let fakeHandler;
	let fakeElem;

	const copyText = () => {
		this.destroy();

		const isRTL = document.documentElement.getAttribute('dir') == 'rtl';

		fakeHandlerCallback = () => {
			this.destroy();
		};
		fakeHandler = container.addEventListener('click', fakeHandlerCallback) || true;

		fakeElem = document.createElement('textarea');
		fakeElem.style.fontSize = '12pt';
		fakeElem.style.border = '0';
		fakeElem.style.padding = '0';
		fakeElem.style.margin = '0';
		fakeElem.style.position = 'absolute';
		fakeElem.style[isRTL ? 'right' : 'left'] = '-9999px';

		const yPosition = window.pageYOffset || document.documentElement.scrollTop;
		fakeElem.style.top = `${yPosition}px`;
		fakeElem.setAttribute('readonly', '');
		fakeElem.value = text;
		container.appendChild(fakeElem);
		selectedText = select(fakeElem);

		let isSuccessful = false;
		try {
			isSuccessful = document.execCommand(action);
		} catch (err) {
			isSuccessful = false;
		}

		if (isSuccessful) {
			if (onComplete != null) {
				onComplete({
					action,
					text: selectedText,
					element
				});
			}
		} else {
			if (onError != null) {
				onError({
					action,
					text: selectedText,
					element
				});
			}
		}

		if (element) element.focus();
		window.getSelection().removeAllRanges();
	};

	this.destroy = () => {
		if (fakeHandler) {
			container.removeEventListener('click', fakeHandlerCallback);
			fakeHandler = null;
			fakeHandlerCallback = null;
		}
		if (fakeElem) {
			container.removeChild(fakeElem);
			fakeElem = null;
		}
	};

	copyText();
}

function Clipboard(element, options) {
	const action = options.action || 'copy';
	const text = options.text;
	const onComplete = options.onComplete != undefined ? options.onComplete : null;
	const onError = options.onError != undefined ? options.onError : null;
	let clipboardAction = null;
	let listener;

	const init = (element) => {
		listener = listenSelector(element, 'click', (e) => {
			this.onClick(e);
		});
	};

	this.onClick = ({ delegateTarget, currentTarget }) => {
		const element = delegateTarget || currentTarget;
		if (clipboardAction) {
			clipboardAction.destroy();
			clipboardAction = null;
		}
		clipboardAction = new ClipboardAction({
			action,
			text,
			container: document.body,
			element,
			onComplete,
			onError
		});
	};

	this.destroy = () => {
		listener.destroy();
		listener = null;
		if (clipboardAction) {
			clipboardAction.destroy();
			clipboardAction = null;
		}
	};

	init(element);
}

export default Clipboard;
